home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / tcpip / amiga / asrc29p.lha / ax25.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-29  |  11.2 KB  |  457 lines

  1. /* Low level AX.25 frame processing - address header */
  2.  
  3. #include <stdio.h>
  4. #include "global.h"
  5. #include "config.h"
  6. #include "mbuf.h"
  7. #include "iface.h"
  8. #include "timer.h"
  9. #include "arp.h"
  10. #include "slip.h"
  11. #include "ax25.h"
  12. #include "lapb.h"
  13. #include "netrom.h"
  14. #include "ip.h"
  15. #include <ctype.h>
  16.  
  17. static int axsend __ARGS((struct iface *iface,char *dest,char *source,
  18.     int cmdrsp,int ctl,struct mbuf *data));
  19.  
  20. /* AX.25 broadcast address: "QST-0" in shifted ascii */
  21. char Ax25_bdcst[AXALEN] = {
  22.     'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1,
  23. };
  24. char Mycall[AXALEN];
  25. struct ax_route *Ax_routes[NHASH];    /* Routing table header */
  26. int Digipeat = 1;    /* Controls digipeating */
  27.  
  28. /* Send IP datagrams across an AX.25 link */
  29. int ax_send(bp,iface,gateway,prec,del,tput,rel)
  30. struct mbuf *bp;
  31. struct iface *iface;
  32. int32 gateway;
  33. int prec;
  34. int del;
  35. int tput;
  36. int rel;
  37. {
  38.     char *hw_addr;
  39.     struct ax25_cb *axp;
  40.     struct mbuf *tbp;
  41.  
  42.     struct ax_route *axr;
  43.     char mode;
  44.  
  45.     if(gateway == iface->broadcast) /* This is a broadcast IP datagram */
  46.          return (*iface->output)(iface,Ax25_bdcst,iface->hwaddr,PID_IP,bp);
  47.  
  48.     if((hw_addr = res_arp(iface,ARP_AX25,gateway,bp)) == NULLCHAR)
  49.         return 0;    /* Wait for address resolution */
  50.  
  51.     /* If there's a defined route, get it */
  52.     axr = ax_lookup(hw_addr);
  53.  
  54.     if(axr == NULLAXR) {
  55.         if(iface->flags == DATAGRAM_MODE){
  56.             mode = AX_DATMODE;
  57.         } else {
  58.             mode = AX_VC_MODE;
  59.         }
  60.     } else {
  61.         mode = axr->mode;
  62.         if(mode == AX_DEFMODE) {
  63.             if(iface->flags == DATAGRAM_MODE){
  64.                 mode = AX_DATMODE;
  65.             } else {
  66.                 mode = AX_VC_MODE;
  67.             }
  68.         }    
  69.     }
  70.  
  71.     /* UI frames are used for any one of the following three conditions:
  72.      * 1. The "low delay" bit is set in the type-of-service field.
  73.      * 2. The "reliability" TOS bit is NOT set and the interface is in
  74.      *    datagram mode.
  75.      * 3. The destination is the broadcast address (this is helpful
  76.      *    when broadcasting on an interface that's in connected mode).
  77.      */
  78.     if(del || (!rel && (mode == AX_DATMODE)) || addreq(hw_addr,Ax25_bdcst)){
  79.         /* Use UI frame */
  80.         return (*iface->output)(iface,hw_addr,iface->hwaddr,PID_IP,bp);
  81.     }
  82.     /* Reliability is needed; use I-frames in AX.25 connection */
  83.     if((axp = find_ax25(hw_addr)) == NULLAX25){
  84.         /* Open a new connection */
  85.         axp = open_ax25(iface,iface->hwaddr,hw_addr,
  86.          AX_ACTIVE,Axwindow,s_arcall,s_atcall,s_ascall,-1);
  87.         if(axp == NULLAX25){
  88.             free_p(bp);
  89.             return -1;
  90.         }
  91.     }
  92.     if(axp->state == LAPB_DISCONNECTED){
  93.         est_link(axp);
  94.         lapbstate(axp,LAPB_SETUP);
  95.     }
  96.     /* Insert the PID */
  97.     if((tbp = pushdown(bp,1)) == NULLBUF){
  98.         free_p(bp);
  99.         return -1;
  100.     }
  101.     bp = tbp;
  102.     bp->data[0] = PID_IP;
  103.     if((tbp = segmenter(bp,axp->paclen)) == NULLBUF){
  104.         free_p(bp);
  105.         return -1;
  106.     }
  107.     return send_ax25(axp,tbp,-1);
  108. }
  109. /* Add header and send connectionless (UI) AX.25 packet.
  110.  * Note that the calling order here must match enet_output
  111.  * since ARP also uses it.
  112.  */
  113. int ax_output(iface,dest,source,pid,data)
  114. struct iface *iface;    /* Interface to use; overrides routing table */
  115. char *dest;        /* Destination AX.25 address (7 bytes, shifted) */
  116. char *source;        /* Source AX.25 address (7 bytes, shifted) */
  117. int16 pid;        /* Protocol ID */
  118. struct mbuf *data;    /* Data field (follows PID) */
  119. {
  120.     struct mbuf *bp;
  121.  
  122.     /* Prepend pid to data */
  123.     bp = pushdown(data,1);
  124.     if(bp == NULLBUF){
  125.         free_p(data);
  126.         return -1;
  127.     }
  128.     bp->data[0] = (char)pid;
  129.     return axsend(iface,dest,source,LAPB_COMMAND,UI,bp);
  130. }
  131.  
  132. /* Common subroutine for sendframe() and ax_output() */
  133. static int axsend(iface,dest,source,cmdrsp,ctl,data)
  134. struct iface *iface;    /* Interface to use; overrides routing table */
  135. char *dest;        /* Destination AX.25 address (7 bytes, shifted) */
  136. char *source;        /* Source AX.25 address (7 bytes, shifted) */
  137. int cmdrsp;        /* Command/response indication */
  138. int ctl;        /* Control field */
  139. struct mbuf *data;    /* Data field (includes PID) */
  140. {
  141.     struct mbuf *cbp;
  142.     struct ax25 addr;
  143.     struct ax_route *axr;
  144.     char control;
  145.     char *idest;
  146.     int rval;
  147.  
  148.     /* If the source addr is unspecified, use the interface address */
  149.     if(source[0] == '\0')
  150.         source = iface->hwaddr;
  151.  
  152.     /* If there's a digipeater route, get it */
  153.     axr = ax_lookup(dest);
  154.  
  155.     memcpy(addr.dest,dest,AXALEN);
  156.     memcpy(addr.source,source,AXALEN);
  157.     addr.cmdrsp = cmdrsp;
  158.  
  159.     if(axr != NULLAXR){
  160.         memcpy(addr.digis,axr->digis,axr->ndigis*AXALEN);
  161.         addr.ndigis = axr->ndigis;
  162.         idest = addr.digis[0];
  163.     } else {
  164.         addr.ndigis = 0;
  165.         idest = dest;
  166.     }
  167.  
  168.     addr.nextdigi = 0;
  169.  
  170.     /* Allocate mbuf for control field, and fill in */
  171.     if((cbp = pushdown(data,1)) == NULLBUF){
  172.         free_p(data);
  173.         return -1;
  174.     }
  175.     cbp->data[0] = ctl;
  176.  
  177.     if((data = htonax25(&addr,cbp)) == NULLBUF){
  178.         free_p(cbp);    /* Also frees data */
  179.         return -1;
  180.     }
  181.     /* Sneak a peek at the control field. This kludge is necessary because
  182.      * AX.25 lacks a proper protocol ID field between the address and LAPB
  183.      * sublayers; a control value of UI indicates that LAPB is to be
  184.      * bypassed.
  185.      */
  186.     control = *cbp->data & ~PF;
  187.  
  188.     /* This shouldn't be necessary because redirection has already been
  189.      * done at the IP router layer, but just to be safe...
  190.      */
  191.     if(iface->forw != NULLIF){
  192.         logsrc(iface->forw,iface->forw->hwaddr,control);
  193.         logdest(iface->forw,idest);
  194.         rval = (*iface->forw->raw)(iface->forw,data);
  195.     } else {
  196.         logsrc(iface,iface->hwaddr,control);
  197.         logdest(iface,idest);
  198.         rval = (*iface->raw)(iface,data);
  199.     }
  200.     return rval;
  201. }
  202.  
  203. extern struct iph *Iph;
  204.  
  205. /* Process incoming AX.25 packets.
  206.  * After optional tracing, the address field is examined. If it is
  207.  * directed to us as a digipeater, repeat it.  If it is addressed to
  208.  * us or to QST-0, kick it upstairs depending on the protocol ID.
  209.  */
  210. void ax_recv(iface,bp)
  211. struct iface *iface;
  212. struct mbuf *bp;
  213. {
  214.     struct mbuf *hbp;
  215.     struct mbuf *nbp;
  216.     char control;
  217.     struct ax25 hdr;
  218.     struct ax25_cb *axp;
  219.     struct ax_route *axr;
  220.     char *isrc,*idest;    /* "immediate" source and destination */
  221.     int pid, len;
  222.     struct ip ip;
  223.  
  224.     /* Pull header off packet and convert to host structure */
  225.     if(ntohax25(&hdr,&bp) < 0){
  226.         /* Something wrong with the header */
  227.         free_p(bp);
  228.         return;
  229.     }
  230.  
  231.     /* If there were digis in this packet, then the last digi was the
  232.      * actual transmitter. Otherwise the source is the transmitter.
  233.      */
  234.     if(hdr.ndigis != 0 && hdr.nextdigi != 0)
  235.         isrc = hdr.digis[hdr.nextdigi-1];
  236.     else
  237.         isrc = hdr.source;
  238.  
  239.     /* Log IP address and AX25 link-address */
  240.     len = len_p(bp);
  241.     if(dup_p(&nbp, bp, 0, len) == len) {
  242.         (void) PULLCHAR(&nbp);
  243.         if(PULLCHAR(&nbp) == PID_IP) {
  244.             ntohip(&ip, &nbp);
  245.             if(ip.version == IPVERSION)
  246.                 log_ipheard(ip.source, iface, isrc);
  247.         }
  248.         free_p(nbp);
  249.     }
  250.  
  251.     if(hdr.nextdigi < hdr.ndigis){
  252.         /* Packet hasn't passed all digipeaters yet. See if
  253.          * we have to repeat it.
  254.          */
  255.         if(Digipeat && addreq(hdr.digis[hdr.nextdigi],iface->hwaddr)){
  256.             /* Yes, kick it back out. htonax25 will set the
  257.              * repeated bit.
  258.              */
  259.             hdr.nextdigi++;
  260.             if((hbp = htonax25(&hdr,bp)) != NULLBUF){
  261.                 if(iface->forw != NULLIF){
  262.                     (*iface->forw->raw)(iface->forw,hbp);
  263.                 } else {
  264.                     (*iface->raw)(iface,hbp);
  265.                 }
  266.                 bp = NULLBUF;
  267.             }
  268.         }
  269.         free_p(bp);    /* Dispose if not forwarded */
  270.         return;
  271.     } else
  272.         idest = hdr.dest;
  273.  
  274.     /* Sneak a peek at the control field. This kludge is necessary because
  275.      * AX.25 lacks a proper protocol ID field between the address and LAPB
  276.      * sublayers; a control value of UI indicates that LAPB is to be
  277.      * bypassed.
  278.      */
  279.     control = *bp->data & ~PF;
  280.  
  281.     /* Don't log our own packets if we overhear them, as they're
  282.      * already logged by axsend() and by the digipeater code.
  283.      */
  284.     if(!addreq(isrc,iface->hwaddr)){
  285.         logsrc(iface,isrc,control);
  286.         logdest(iface,idest);
  287.     }
  288.  
  289.     /* If we reach this point, then the packet has passed all digis,
  290.      * but it is not necessarily for us.
  291.      */
  292.     if(bp == NULLBUF){
  293.         /* Nothing left */
  294.         return;
  295.     }
  296.     if(uchar(control) == UI){
  297.         char pid;
  298.  
  299.         (void) pullchar(&bp);
  300.         if(pullup(&bp,&pid,1) != 1)
  301.             return;        /* No PID */
  302.         /* Handle packets. Multi-frame messages are not allowed */
  303.         switch(uchar(pid)){
  304.         case PID_IP:
  305.             if(addreq(hdr.dest,Ax25_bdcst))
  306.                 ip_route(iface,bp,1);    /* Broadcast packet */
  307.             else if(addreq(hdr.dest,iface->hwaddr))
  308.                 ip_route(iface,bp,0);    /* Packet directed at us */
  309.             else free_p(bp);
  310.             break;
  311.         case PID_ARP:
  312.             if(addreq(hdr.dest,iface->hwaddr)
  313.                || addreq(hdr.dest,Ax25_bdcst))
  314.                 arp_input(iface,bp);
  315.             else free_p(bp);
  316.             break;
  317.         case PID_NETROM:
  318.             if(addreq(hdr.dest,Nr_nodebc))
  319.                 nr_nodercv(iface,hdr.source,bp);
  320.             else free_p(bp);
  321.             break;
  322.         case PID_NO_L3:
  323.             if(addreq(hdr.dest,iface->hwaddr))
  324.                 beac_input(iface,hdr.source,bp);
  325.             else free_p(bp);
  326.             break;
  327.         default:
  328.             free_p(bp);
  329.             break;
  330.         }
  331.         return;
  332.     }
  333.     /* Everything from here down is LAPB, so drop anything that's
  334.      * not explicitly for us ...
  335.      */
  336.     if(!addreq(hdr.dest,iface->hwaddr)){
  337.         free_p(bp) ;
  338.         return ;
  339.     }
  340.     /* If there's no locally-set entry in the routing table and
  341.      * this packet has digipeaters, create or update it. Leave
  342.      * local routes alone.
  343.      */
  344.     if(((axr = ax_lookup(hdr.source)) == NULLAXR || axr->type == AX_AUTO)
  345.      && hdr.ndigis > 0){
  346.         char digis[MAXDIGIS][AXALEN];
  347.         int i,j;
  348.  
  349.         /* Construct reverse digipeater path */
  350.         for(i=hdr.ndigis-1,j=0;i >= 0;i--,j++){
  351.             memcpy(digis[j],hdr.digis[i],AXALEN);
  352.             digis[j][ALEN] &= ~(E|REPEATED);
  353.         }
  354.         ax_add(hdr.source,AX_AUTO,digis,hdr.ndigis);
  355.     }
  356.  
  357.     /* Find the source address in hash table */
  358.     if((axp = find_ax25(hdr.source)) == NULLAX25){
  359.         /* Create a new ax25 entry for this guy,
  360.          * insert into hash table keyed on his address,
  361.          * and initialize table entries
  362.          */
  363.         if((axp = cr_ax25(hdr.source)) == NULLAX25){
  364.             free_p(bp);
  365.             return;
  366.         }
  367.         /* Swap source and destination */
  368.         memcpy(axp->remote,hdr.source,AXALEN);
  369.         memcpy(axp->local,hdr.dest,AXALEN);
  370.         axp->iface = iface;
  371.     }
  372.     if(hdr.cmdrsp == LAPB_UNKNOWN)
  373.         axp->proto = V1;    /* Old protocol in use */
  374.  
  375.     lapb_input(axp,hdr.cmdrsp,bp);
  376. }
  377. /* General purpose AX.25 frame output */
  378. int
  379. sendframe(axp,cmdrsp,ctl,data)
  380. struct ax25_cb *axp;
  381. int cmdrsp;
  382. int ctl;
  383. struct mbuf *data;
  384. {
  385.     return axsend(axp->iface,axp->remote,axp->local,cmdrsp,ctl,data);
  386. }
  387. void
  388. axarp()
  389. {
  390.     arp_init(ARP_AX25,AXALEN,PID_IP,PID_ARP,10,Ax25_bdcst,pax25,setcall);
  391. }
  392. /* Find a route for an AX.25 address */
  393. struct ax_route *
  394. ax_lookup(target)
  395. char *target;
  396. {
  397.     register struct ax_route *axr;
  398.  
  399.     for(axr = Ax_routes[ax25hash(target)]; axr != NULLAXR; axr = axr->next){
  400.         if(addreq(axr->target,target))
  401.             break;
  402.     }
  403.     return axr;
  404. }
  405. /* Add an entry to the AX.25 routing table */
  406. struct ax_route *
  407. ax_add(target,type,digis,ndigis)
  408. char *target;
  409. int type;
  410. char digis[][AXALEN];
  411. int ndigis;
  412. {
  413.     int16 hval;
  414.     register struct ax_route *axr;
  415.  
  416.     if(ndigis < 0 || ndigis > MAXDIGIS)
  417.         return NULLAXR;
  418.  
  419.     if((axr = ax_lookup(target)) == NULLAXR){
  420.         axr = (struct ax_route *)callocw(1,sizeof(struct ax_route));
  421.         hval = ax25hash(target);
  422.         axr->prev = NULLAXR;
  423.         axr->next = Ax_routes[hval];
  424.         if(axr->next != NULLAXR)
  425.             axr->next->prev = axr;
  426.         Ax_routes[hval] = axr;
  427.         memcpy(axr->target,target,AXALEN);
  428.         axr->ndigis = ndigis;
  429.     }
  430.     axr->type = type;
  431.     axr->mode = AX_DEFMODE;        /* set mode to default */
  432.     if(axr->ndigis != ndigis)
  433.         axr->ndigis = ndigis;
  434.  
  435.     memcpy(axr->digis,digis[0],ndigis*AXALEN);
  436.     return axr;
  437. }
  438. int
  439. ax_drop(target)
  440. char *target;
  441. {
  442.     register struct ax_route *axr;
  443.  
  444.     if((axr = ax_lookup(target)) == NULLAXR)
  445.         return -1;
  446.  
  447.     if(axr->next != NULLAXR)
  448.         axr->next->prev = axr->prev;
  449.     if(axr->prev != NULLAXR)
  450.         axr->prev->next = axr->next;
  451.     else
  452.         Ax_routes[ax25hash(target)] = axr->next;
  453.     free((char *)axr);
  454.     return 0;
  455. }
  456.  
  457.